import { Ref, ref, getCurrentInstance } from 'vue';
import _ from 'lodash';
import OpenSeadragon, { MouseTracker } from 'openseadragon';
import { fabric } from "fabric";
import useFabricTool from './useFabricTool';
import { useMarkLesionStore } from '@/store';
import { updateAnnoData } from '@/api/readPathology/readPathology';
import type { StaticCanvas, Canvas, IEvent } from 'fabric/fabric-impl';
import type * as Temp from './type.d';
import type * as Type from '@/api/readPathology/readPathology.d';
import { Message } from '@arco-design/web-vue';

export default function useFabric(
    viewer: Ref<any>, 
    slideInfo: Ref<Temp.SlideInfo>, 
    currentItem: Ref<number>, 
    showLesionList: Ref<Temp.NidusList[]>,
    alrId: Ref<number>,
    arListData: Ref<Type.ArItem[] | null>,
    mouseTracker: Ref<OpenSeadragon.MouseTracker | undefined>,
    currentSubmenuItem: Ref<string | number>,
    getInitData: Function,
    currentMiniSeriesSet: Ref<Temp.ShowComponentObj>,
    lesionResultData: {
        dataList: Type.LesionResultItem[]
    },
) {
    // 工具容器
    const fabricToolContainer = ref();
    // 工具容器div
    const fabricToolCanvas = ref();
    // 工具画布
    const fabricCanvas = ref<Canvas | null>(null);
    // 工具笔刷初始颜色
    const pencilColor = ref<string>('#448E97');
    // 工具笔刷初始宽度
    const pencilWidth = ref<number>(1);
    // 初始实际缩放比例
    const actualZoom = ref();
    // 初始容器宽
    const containerWidth = ref<number>(1);
    // 初始容器高
    const containerHeight = ref<number>(1);
    // canvas的缩放倍率值
    const canvasZoom = ref<number>(0);
    // opensed的缩放倍率值
    const viewportZoomRef = ref<number>(0);

    // 获取标注画的事件
    const { doDrawing, mouseDown, mouseMove, mouseUp } = useFabricTool(fabricCanvas, viewer, pencilColor, pencilWidth, currentItem, showLesionList, slideInfo, alrId, arListData, getInitData);

    // 获取存储对象
    const markLesionStore = useMarkLesionStore();

    // 初始化创建标注工具
    const initMarkTool = () => {
        // 注销标记画布
        window.frabicCanvas && window.frabicCanvas.dispose();
        // 创建 canvas 画布容器
        fabricToolContainer.value = document.createElement("div");
        fabricToolContainer.value.setAttribute("id", "canvasDiv");
        fabricToolContainer.value.style.position = "absolute";
        fabricToolContainer.value.style.left = fabricToolContainer.value.style.top = "0";
        fabricToolContainer.value.style.width = fabricToolContainer.value.style.height = "100%";
        // 将容器放进 openSeadragon 中
        viewer.value.canvas.appendChild(fabricToolContainer.value);
        // 创建画布
        fabricToolCanvas.value = document.createElement("canvas");
        fabricToolCanvas.value.setAttribute("id", "canvas");
        // 将画布放入 画布容器中
        fabricToolContainer.value.appendChild(fabricToolCanvas.value);
        // fabric.Object.prototype.set({
        //     hoverCursor: "pointer",
        // });
        window.frabicCanvas = new fabric.Canvas("canvas", {
            // enableRetinaScaling: true,
            centeredScaling: true, // 全局所有元素都生效
            // 选择是否完全包含
            selectionFullyContained: false,
            // 是否可按住画布进行缩放
            enableRetinaScaling: false,
            // 是否可选择 false为不可以被选择 true可以被选择
            selection: true,
            // preserveObjectStacking: true,
            // 精简输出json标注对象
            includeDefaultValues: false,
            // 放大到一定倍数，会跳过部分渲染，需要关闭
            skipOffscreen: false, //跳过当前视口中未包含的对象的渲染。在画布拥挤和使用缩放/平移的应用程序中可能会有很大帮助如果对象边界框的一角在画布上，则对象将被渲染。
            // 是否以中心店缩放 默认是true以中心点缩放 false不是中心点
            // centeredScaling: false,
            // 对象是都可以固定一边被进行拉伸 默认是false true为可以固定
            // uniScaleTransform: true
            // 设置默认框选样式的选中色
            // selectionColor: 'rgba(255, 255, 255, 0)',
        });
        // 设置笔刷颜色和宽度
        window.frabicCanvas.freeDrawingBrush.color = pencilColor.value;
        window.frabicCanvas.freeDrawingBrush.width = pencilWidth.value;
        window.frabicCanvas?.setWidth(viewer.value.container.clientWidth);
        window.frabicCanvas?.setHeight(viewer.value.container.clientHeight);

        // 将当前画布共享值阅片页全局
        linterViewerEvent();
        linterMouseEvent();
        linterFabricEvent();
    };

    let downPoint = {
        x: 0,
        y: 0
    }
    let upPoint = {
        x: 0,
        y: 0
    }
    let currentType = false;
    let isSelectObj: fabric.Object | null = null;
    // 重置窗口
    const resize = () => {
        containerWidth.value = viewer.value.container.clientWidth;
        containerHeight.value = viewer.value.container.clientHeight;
        fabricToolContainer.value.setAttribute("width", containerWidth.value);
        fabricToolCanvas.value.setAttribute("width", containerWidth.value);
        fabricToolContainer.value.setAttribute("height", containerHeight.value);
        fabricToolCanvas.value.setAttribute("height", containerHeight.value);
        window.frabicCanvas?.setWidth(containerWidth.value);
        window.frabicCanvas?.setHeight(containerHeight.value);
    };

    // 修正窗口
    const resizeCanvas = () => {
        
        const origin = new OpenSeadragon.Point(0, 0);
        const viewportWindowPoint = viewer.value.viewport.viewportToWindowCoordinates(origin);
        const x = Math.round(viewportWindowPoint.x);
        const y = Math.round(viewportWindowPoint.y);
        const canvasOffset = fabricToolContainer.value.getBoundingClientRect();
        const pageScroll = OpenSeadragon.getPageScroll();
        window.frabicCanvas?.absolutePan(
            new fabric.Point(canvasOffset.left - x + pageScroll.x, canvasOffset.top - y + pageScroll.y)
        );
    }

    // 初始监听鼠标事件
    const linterMouseEvent = () => {
        window.frabicCanvas?.on('mouse:move', (options: IEvent<MouseEvent>) => {
            if (doDrawing.value) {
                mouseMove(options);
            };
            const activeObject = window.frabicCanvas?.getActiveObject();
            
            if (isSelectObj && activeObject) {
                viewer.value.setMouseNavEnabled(false);
            }
        });
        window.frabicCanvas?.on('mouse:down', (options: IEvent<MouseEvent>) => {
            if (options.target && !doDrawing.value) {
                // 记录目标对象存在情况下的当前鼠标坐标
                const offsetX = window.frabicCanvas.calcOffset().viewportTransform[4];
                // 记录画布鼠标按下时的y偏移量
                const offsetY = window.frabicCanvas.calcOffset().viewportTransform[5];
                // 根据x偏移量计算实际x坐标
                const x: number = Math.round(options.e.offsetX - offsetX);
                // 根据y偏移量计算实际y坐标
                const y: number = Math.round(options.e.offsetY - offsetY);
                downPoint = {
                    x,
                    y
                }
                if (options.target.type !== 'group') {
                    // 标注画布鼠标按下，并且标注存在，并让标注聚焦病灶列表
                    const currentItenMarkObj = showLesionList.value.filter(item => item.markInfo.left === options.target?.left && item.markInfo.top === options.target?.top);
                    // 设置当前选择的id，将病灶列表聚焦到当前选择病灶
                    currentSubmenuItem.value = currentItenMarkObj[0].disease.id;
                    // 根据当前选择的病灶设置当前聚焦的小征象
                    currentMiniSeriesSet.value = currentItenMarkObj[0].disease.list;
                    isSelectObj = options.target;
                    window.frabicCanvas?.setActiveObject(currentItenMarkObj[0].markInfo);
                }
            } else if([4, 6, 7].includes(currentItem.value)) {
                mouseDown(options);
                linterMouseEvent();
            };
            if (!options.target) {
                isSelectObj = null;
            }
        });
        window.frabicCanvas?.on('mouse:up', async (options: any) => {
            [4, 6, 7].includes(currentItem.value) && mouseUp(options);
            if (isSelectObj && isSelectObj.type !== 'group') {
                // 设置最终结果点位数据
                let resultData = {
                    point1: {
                        x: 0,
                        y: 0
                    },
                    point2: {
                        x: 0,
                        y: 0
                    }
                }
                // 记录移动结束的点位信息
                // 记录目标对象存在情况下的当前鼠标坐标
                const offsetX = window.frabicCanvas.calcOffset().viewportTransform[4];
                // 记录画布鼠标按下时的y偏移量
                const offsetY = window.frabicCanvas.calcOffset().viewportTransform[5];
                // 根据x偏移量计算实际x坐标
                const x: number = Math.round(options.e.offsetX - offsetX);
                // 根据y偏移量计算实际y坐标
                const y: number = Math.round(options.e.offsetY - offsetY);
                upPoint = {
                    x,
                    y
                };
                // 计算移动距离
                const moveSpaceX = upPoint.x - downPoint.x;
                const moveSpaceY = upPoint.y - downPoint.y;
                // 排除点击抬起没移动鼠标
                if (moveSpaceX === 0 && moveSpaceY === 0) return;
                // 通过病灶列表过滤出当前操作的frabic图形对象
                const currentCanvasObj = showLesionList.value.filter(item => item.disease.id === currentSubmenuItem.value);
                if (currentCanvasObj.length !== 0) {
                    // 通过得到的当前数据对象解构出相应宽度，高度，left值，top值做后续处理
                    const { width, height, left, top, id, ...newMarkInfo } = currentCanvasObj[0]?.markInfo;

                    // 通过数据得到当前接口返回数据
                    const currentResultList = lesionResultData.dataList.filter(item => item.id === currentCanvasObj[0].disease.id);

                    // 通过过滤的接口数据解构出当前点位信息
                    const { data, acZoom, version } = JSON.parse(currentResultList[0].result || '{}');
                    const newData = {
                        // point1: { ...changePoint(viewer, data.point1) },
                        // point2: { ...changePoint(viewer, data.point2) }
                        point1: { ...data.point1 },
                        point2: { ...data.point2 }
                    }
                    resultData = _.cloneDeep(newData);
                    // 对角线拉伸图形
                    if (options.transform?.action === 'scale') {
                        // 左上控制点
                        if (options.transform.corner === 'tl') {
                            resultData.point1.x += moveSpaceX;
                            resultData.point1.y += moveSpaceY;
                        }
                        // 右下控制点
                        if (options.transform.corner === 'br') {
                            resultData.point2.x += moveSpaceX;
                            resultData.point2.y += moveSpaceY;
                        }
                        // 左下控制点
                        if (options.transform.corner === 'bl') {
                            resultData.point1.x += moveSpaceX;
                            resultData.point2.y += moveSpaceY;
                        }
                        // 右上控制点
                        if (options.transform.corner === 'tr') {
                            resultData.point1.y += moveSpaceY;
                            resultData.point2.x += moveSpaceX;
                        }
                    };

                    // 拉伸宽度
                    if (options.transform?.action === 'scaleX') {
                        // 左控制点拉伸宽度
                        if (options.transform.corner === 'ml') {
                            // 计算起始点
                            resultData.point1.x += moveSpaceX;
                        };
                        // 右控制点右拉伸宽度
                        if (options.transform.corner === 'mr') {
                            resultData.point2.x += moveSpaceX;
                        };
                    };

                    // 拉伸高度
                    if (options.transform?.action === 'scaleY') {
                        // 上控制点拉伸高度
                        if (options.transform.corner === 'mt') {
                            resultData.point1.y += moveSpaceY;
                        }
                        // 下控制点拉伸高度
                        if (options.transform.corner === 'mb') {
                            resultData.point2.y += moveSpaceY;
                        }
                    };

                    // 平移图形
                    if (options.transform?.action === 'drag') {
                        resultData.point1.x += moveSpaceX;
                        resultData.point1.y += moveSpaceY;
                        resultData.point2.x += moveSpaceX;
                        resultData.point2.y += moveSpaceY;
                    };

                    // 调用更新标注接口
                    const resultDataObj = {
                        data: _.cloneDeep(resultData),
                        acZoom,
                        version
                    }
                    const params = {
                        alrId: currentResultList[0].id,
                        result: JSON.stringify(resultDataObj),
                        color: currentResultList[0].color
                    }
                    const res = await updateAnnoData(params);
                    Message.success('修改成功！');
                    // 根据病灶列表的数据清除当前画布标注
                    // window.frabicCanvas?.clear();
                    // 重新执行查询数据
                    // getInitData();
                }
            } else {
                currentSubmenuItem.value = '';
            }
        });
    };

    // 设置大图监听事件
    const linterViewerEvent = () => {
        let nonPrimaryDown = false;
        let dragPosition = {
            x: 0,
            y: 0
        };
        let zoomPositon = {
            x: 0,
            y: 0
        };
        let primaryDown = false;
        mouseTracker.value?.setTracking(true);
        const moveHandler = (event: any) => {
            // 1是左键 0是移动 2是右键
            // if (event.buttons === 0 || event.buttons === 1) {
            //     if ([4, 6, 7].includes(currentItem.value)) {
            //         viewer.value.setMouseNavEnabled(false);
            //         linterMouseEvent();
            //     }
            // }
            if (event.buttons === 2) {
                if (nonPrimaryDown) {
                    const delta = event.position.minus(dragPosition);
                    viewer.value.viewport.panBy(viewer.value.viewport.deltaPointsFromPixels(delta.negate()));
                    dragPosition = event.position.clone();
                }
            }
        }
        let canvasDownPoint = {
            x: 0,
            y: 0
        }
        // 鼠标移动
        mouseTracker.value && (mouseTracker.value.moveHandler = moveHandler);
        viewer.value.addHandler('canvas-press', (event: any) => {
            canvasDownPoint = event.position.clone();
            if ([0, 1].includes(currentItem.value)) {
                // 为查看工具类
                primaryDown = true;
                zoomPositon = event.position.clone();
            }
        });
        viewer.value.addHandler('canvas-release', (event: any) => {
            primaryDown = false;
            if (!currentType && (canvasDownPoint.x !== event.position.clone().x && canvasDownPoint.y !== event.position.clone().y)) {
                // 根据病灶列表的数据清除当前画布标注
                window.frabicCanvas?.clear();
                // 重新执行查询数据
                getInitData();
            }
        });
        viewer.value.addHandler('canvas-drag', (event: any) => {
            if (primaryDown) {
                const viewerDom = document.getElementById('viewer')!;
                const cneterY = viewerDom?.clientHeight / 2;
                if (zoomPositon.y < cneterY) {
                    const factor = Math.pow( event.eventSource.zoomPerScroll, 1 );
                    primaryDown = true;
                    const point = new OpenSeadragon.Point(zoomPositon.x, zoomPositon.y)
                    viewer.value.viewport.zoomBy(factor, viewer.value.viewport.pointFromPixel(point, false));
                }
                if (zoomPositon.y > cneterY) {
                    const factor = Math.pow( event.eventSource.zoomPerScroll, -1 );
                    primaryDown = true;
                    const point = new OpenSeadragon.Point(zoomPositon.x, zoomPositon.y)
                    viewer.value.viewport.zoomBy(factor, viewer.value.viewport.pointFromPixel(point, false));
                }
            }
        });
        viewer.value.addHandler('canvas-nonprimary-press', (event: any) => {
            if (event.button === 2) {
                nonPrimaryDown = true;
                dragPosition = event.position.clone();
            };
        });
        viewer.value.addHandler('canvas-nonprimary-release', (event: any) => {
            if (event.button === 2) {
                nonPrimaryDown = false;
                viewer.value.viewport.applyConstraints();
            };
        });
        // 鼠标滚动计算标注
        viewer.value.addHandler('canvas-scroll', (event: any) => {
            if (!primaryDown) {
                // 根据病灶列表的数据清除当前画布标注
                window.frabicCanvas?.clear();
                // 重新执行查询数据
                getInitData();
            }
        });
    }
    
    // 设置绘制监听事件
    const linterFabricEvent = () => {
        const listenerDom = document.getElementById('content-viewer-container')!;
        listenerDom.addEventListener('keydown', (event: any) => {
            const keyNum = window.event ? event.keyCode : event.which;
            if (keyNum === 32) {
                currentType = !currentType;
            }
        })
        listenerDom.addEventListener('keyup', (event: any) => {
            const keyNum = window.event ? event.keyCode : event.which;
            if (keyNum === 32) {
                const enabled = viewer.value.isMouseNavEnabled();
                if (!currentType) {
                    viewer.value.setMouseNavEnabled(false);
                    linterMouseEvent();
                    Message.info('已切换为绘制模式！');
                } else {
                    viewer.value.setMouseNavEnabled(true);
                    Message.info('已切换为查看模式！');
                    viewer.value.zoomPerScroll = 1.1;
                    viewer.value.panHorizontal = true;
                    viewer.value.panVertical = true;
                }
            }
        })
    }

    return {
        fabricToolContainer,
        fabricToolCanvas,
        fabricCanvas,
        pencilColor,
        pencilWidth,
        initMarkTool,
        resize,
        resizeCanvas,
        linterMouseEvent
    };
};